﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Generated;
using ILRuntime.Runtime.Intepreter;
using UnityEngine;

namespace Smart.Model
{
    public static class ILHelper
	{
        static void RegisterMethod(ILRuntime.Runtime.Enviorment.AppDomain appdomain)
        {
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Boolean>();
            appdomain.DelegateManager.RegisterFunctionDelegate<TableHandle, System.Object>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.String, System.Action, System.Boolean>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.String>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<byte[]>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.String>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.Int32, System.String[]>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.Int32, System.String>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.IAsyncResult>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Int32>();
            appdomain.DelegateManager.RegisterFunctionDelegate<UnityEngine.Transform>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Object, System.Object, System.Boolean>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Object, System.Object, System.Int32>();
            appdomain.DelegateManager
                .RegisterFunctionDelegate<ILRuntime.Runtime.Intepreter.ILTypeInstance, System.Boolean>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Object, System.Int64>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Boolean>();
            appdomain.DelegateManager.RegisterMethodDelegate<ILRuntime.Runtime.Intepreter.ILTypeInstance>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject, System.Boolean>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject, UnityEngine.Vector2>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Single>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.Object, System.Object, System.Boolean>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject, System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.Boolean>();
            appdomain.DelegateManager
                .RegisterFunctionDelegate<ILRuntime.Runtime.Intepreter.ILTypeInstance,
                    ILRuntime.Runtime.Intepreter.ILTypeInstance, System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.Vector3>();
            appdomain.DelegateManager.RegisterFunctionDelegate<System.String, System.Int32, System.Char, System.Char>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject, UnityEngine.GameObject>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.GameObject, System.Int32, System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<TableHandle>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.UInt32, System.Object>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int64, System.Int64>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Object[], System.Int32>();
            appdomain.DelegateManager.RegisterMethodDelegate<UnityEngine.TextAsset>();
            appdomain.DelegateManager.RegisterMethodDelegate<List<object>>();
            appdomain.DelegateManager.RegisterMethodDelegate<byte[], int, int>();
            appdomain.DelegateManager.RegisterMethodDelegate<ILTypeInstance>();
            appdomain.DelegateManager.RegisterMethodDelegate<Smart.Model.TableData>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Object, Smart.Model.TableHandle>();
            appdomain.DelegateManager.RegisterMethodDelegate<System.Int32, System.Object>();
            appdomain.DelegateManager.RegisterMethodDelegate<Smart.Model.FrameData>();
        }

        static void RegisterDelegate(ILRuntime.Runtime.Enviorment.AppDomain appdomain)
        {
            appdomain.DelegateManager.RegisterDelegateConvertor<System.Threading.ThreadStart>((act) =>
            {
                return new System.Threading.ThreadStart(() => { ((Action)act)(); });
            });
            appdomain.DelegateManager.RegisterDelegateConvertor<System.AsyncCallback>((act) =>
            {
                return new System.AsyncCallback((ar) => { ((Action<System.IAsyncResult>)act)(ar); });
            });
            appdomain.DelegateManager.RegisterDelegateConvertor<System.Comparison<System.Object>>((act) =>
            {
                return new System.Comparison<System.Object>((x, y) =>
                {
                    return ((Func<System.Object, System.Object, System.Int32>)act)(x, y);
                });
            });
            appdomain.DelegateManager
                .RegisterDelegateConvertor<System.Predicate<ILRuntime.Runtime.Intepreter.ILTypeInstance>>((act) =>
                {
                    return new System.Predicate<ILRuntime.Runtime.Intepreter.ILTypeInstance>((obj) =>
                    {
                        return ((Func<ILRuntime.Runtime.Intepreter.ILTypeInstance, System.Boolean>)act)(obj);
                    });
                });
            appdomain.DelegateManager
                .RegisterDelegateConvertor<System.Comparison<ILRuntime.Runtime.Intepreter.ILTypeInstance>>((act) =>
                {
                    return new System.Comparison<ILRuntime.Runtime.Intepreter.ILTypeInstance>((x, y) =>
                    {
                        return ((Func<ILRuntime.Runtime.Intepreter.ILTypeInstance,
                            ILRuntime.Runtime.Intepreter.ILTypeInstance, System.Int32>)act)(x, y);
                    });
                });
            appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction>((action) =>
            {
                return new UnityEngine.Events.UnityAction(() =>
                {
                    ((Action)action)();
                });
            });
            appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction<string>>((action) =>
            {
                return new UnityEngine.Events.UnityAction<string>((stringValue) =>
                {
                    ((Action<string>)action)(stringValue);
                });
            });
        }

        public static void InitILRuntime(ILRuntime.Runtime.Enviorment.AppDomain appdomain)
		{
            // 注册委托
            RegisterMethod(appdomain);
            // 注册委托重定向
            RegisterDelegate(appdomain);
            // 注册适配器具有[ILAdapter]标签
            Assembly assembly = typeof(GameApplication).Assembly;
            foreach (Type type in assembly.GetTypes())
            {
                object[] attrs = type.GetCustomAttributes(typeof(ILAdapterAttribute), false);
                if (attrs.Length == 0)
                {
                    continue;
                }
                object obj = Activator.CreateInstance(type);
                CrossBindingAdaptor adaptor = obj as CrossBindingAdaptor;
                if (adaptor == null)
                {
                    continue;
                }
                appdomain.RegisterCrossBindingAdaptor(adaptor);
            }

            CLRBindings.Initialize(appdomain);

            //LitJson.JsonMapper.RegisterILRuntimeCLRRedirection(appdomain);
        }
	}
}